//
//  PortfolioDataService.swift
//  Crypto
//
//  Created by DaleGuo on 2023/9/24.
//

import CoreData
import Foundation

/// 构建PortfolioData的Coredata Service
class PortfolioDataService {
    private let container: NSPersistentContainer    
    private let containerName: String = "PortfolioContainer" // 要和PortfolioContainer.xcdatamodeld名相同
    private let entityName: String = "PortfolioEntity"
    @Published var savedEntities: [PortfolioEntity] = []    // 不同于CoinModel数据

    init() {
        container = NSPersistentContainer(name: containerName)
        container.loadPersistentStores { _, error in
            if let error = error {
                print("Error loading core data! \(error)")
            }

            self.getPortfolio()
        }
    }

    // public
    func updatePortfolio(coin: CoinModel, amount: Double) {
        // 检查coredata中是否已经有此coin
        if let entity = savedEntities.first(where: { $0.coinID == coin.id }) {
            if amount > 0 {
                // amount为用户输入
                update(entity: entity, amount: amount)
            } else {
                delete(entity: entity)
            }
        } else {
            // coreData中没有此
            add(coin: coin, amount: amount)
        }
    }

    // private

    private func getPortfolio() {
        let request = NSFetchRequest<PortfolioEntity>(entityName: entityName)

        do {
            savedEntities = try container.viewContext.fetch(request)
        } catch {
            print("Error fetching portfolio entity: \(error)")
        }
    }

    /// 在vm中传递的是coin，并在Servcie中解开为portfolioEntity
    private func add(coin: CoinModel, amount: Double) {
        let entity = PortfolioEntity(context: container.viewContext) // 一个空数据的对象
        entity.coinID = coin.id
        entity.amount = amount

        applyChanges()
    }

    private func update(entity: PortfolioEntity, amount: Double) {
        entity.amount = amount
        applyChanges()
    }

    private func delete(entity: PortfolioEntity) {
        container.viewContext.delete(entity)
        applyChanges()
    }

    private func save() {
        do {
            try container.viewContext.save()
        } catch {
            print("Error saving portfolio data! \(error)")
        }
    }

    private func applyChanges() {
        save()
        getPortfolio()
    }
}
